/**
    Copyright (C) 2011  Alexander Vollmer

    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

package org.jefb.service.impl;

import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.util.Date;
import java.util.List;

import javax.annotation.PostConstruct;

import org.apache.commons.io.FileUtils;
import org.apache.log4j.DailyRollingFileAppender;
import org.apache.log4j.Level;
import org.apache.log4j.PatternLayout;
import org.jefb.entity.RoleEntity;
import org.jefb.entity.UserEntity;
import org.jefb.sec.entity.UserRight;
import org.jefb.service.IAppInitService;
import org.jefb.service.ICommonPersistenceService;
import org.jefb.util.ConfigHolder;
import org.jefb.util.CryptographyUtil;
import org.jefb.util.service.impl.Config;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

@Service
public class AppInitService implements IAppInitService {

	private static Logger log = LoggerFactory.getLogger(AppInitService.class);
	@Autowired
	private ICommonPersistenceService commonPersistenceService;
	
	private KeyPair rsaKeyPair;
	
	private Config config;
	
	/**
	 * Initialize application.
	 */
	@PostConstruct
	public void initApplication() {
		initLogger();
		log.info("Logger initialized.");
		
		log.info("Initialising application...");
		log.info("Initialising cryptography...");
		KeyPairGenerator keyGen = CryptographyUtil.createRSAKeyPairGenerator();
		rsaKeyPair = keyGen.genKeyPair();
		
		initDatabase();
	}
	
	/**
	 * Initialize application database
	 */
	private void initDatabase(){
		//insert or refresh required entities.
		UserEntity example = new UserEntity();
		example.setUsername("admin");
		List<UserEntity> users = commonPersistenceService.findAllByExample(example);
		UserEntity adminUser;
		if(users.size()>0){
			adminUser = users.get(0);
		}else{
			adminUser = new UserEntity();
			adminUser.setUsername("admin");
			adminUser.setPassword(CryptographyUtil.encodeSHA256("admin"));
			adminUser.setHomeDir(FileUtils.getTempDirectoryPath());
			
			adminUser.getUserRights().add(UserRight.ALL);
			commonPersistenceService.persistEntity(adminUser);
			
			RoleEntity role = new RoleEntity();
			role.setAuthority("SUPERUSER");
			role.setCreationTime(new Date());
			commonPersistenceService.persistEntity(role);
		}
	}
	
	/**
	 * Initialize application logger.
	 */
	private void initLogger(){
		DailyRollingFileAppender rollingFileAppender = new DailyRollingFileAppender();
		rollingFileAppender.setDatePattern(ConfigHolder.getProperty("app_logger.log_date_pattern_for_rollover"));
		rollingFileAppender.setFile(ConfigHolder.getProperty("app_logger.log_file"));
		PatternLayout patternLayout = new PatternLayout(ConfigHolder.getProperty("app_logger.log_layout"));
		rollingFileAppender.setLayout(patternLayout);
		rollingFileAppender.activateOptions();
		org.apache.log4j.Logger rootLogger = org.apache.log4j.Logger.getRootLogger();
		String logLevel = ConfigHolder.getProperty("app_logger.log_level");
		if(logLevel!=null){
			if(logLevel.equalsIgnoreCase("OFF")){
				rootLogger.setLevel(Level.OFF);
			}
			if(logLevel.equalsIgnoreCase("FATAL")){
				rootLogger.setLevel(Level.FATAL);
			}
			if(logLevel.equalsIgnoreCase("ERROR")){
				rootLogger.setLevel(Level.ERROR);
			}
			if(logLevel.equalsIgnoreCase("WARN")){
				rootLogger.setLevel(Level.WARN);
			}
			if(logLevel.equalsIgnoreCase("INFO")){
				rootLogger.setLevel(Level.INFO);
			}
			if(logLevel.equalsIgnoreCase("DEBUG")){
				rootLogger.setLevel(Level.DEBUG);
			}
			if(logLevel.equalsIgnoreCase("ALL")){
				rootLogger.setLevel(Level.ALL);
			}
		}
		rootLogger.addAppender(rollingFileAppender);
	}

	public PrivateKey getPrivateKey() {
		return rsaKeyPair.getPrivate();
	}

	public PublicKey getPublicKey() {
		return rsaKeyPair.getPublic();
	}

	public void setConfig(Config config) {
		this.config = config;
	}

	public Config getConfig() {
		return config;
	}

	public void setCommonPersistenceService(ICommonPersistenceService commonPersistenceService) {
		this.commonPersistenceService = commonPersistenceService;
	}

	public ICommonPersistenceService getCommonPersistenceService() {
		return commonPersistenceService;
	}
}
